package ext.generic.project.reports;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Properties;
import java.util.PropertyResourceBundle;
import java.util.TimeZone;
import java.util.TreeMap;
import java.util.Vector;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import wt.calendar.StandardCalendarService;
import wt.change2.ChangeActivity2;
import wt.change2.ChangeHelper2;
import wt.change2.Changeable2;
import wt.change2.WTChangeActivity2;
import wt.change2.WTChangeIssue;
import wt.change2.WTChangeIssueMaster;
import wt.change2.WTChangeOrder2;
import wt.doc.WTDocument;
import wt.epm.EPMDocument;
import wt.fc.ObjectIdentifier;
import wt.fc.ObjectReference;
import wt.fc.Persistable;
import wt.fc.PersistenceHelper;
import wt.fc.QueryResult;
import wt.fc.ReferenceFactory;
import wt.fc.WTObject;
import wt.fc.collections.WTCollection;
import wt.inf.container.WTContainer;
import wt.org.OrganizationServicesHelper;
import wt.org.WTGroup;
import wt.org.WTPrincipal;
import wt.org.WTUser;
import wt.part.WTPart;
import wt.projmgmt.admin.Project2;
import wt.projmgmt.execution.ProjectPlan;
import wt.projmgmt.resource.Deliverable;
import wt.projmgmt.resource.ProjResourceHelper;
import wt.query.AttributeRange;
import wt.query.ClassAttribute;
import wt.query.OrderBy;
import wt.query.QuerySpec;
import wt.query.SearchCondition;
import wt.session.SessionHelper;
import wt.session.SessionServerHelper;
import wt.util.WTContext;
import wt.util.WTException;
import wt.util.WTProperties;
import wt.util.WTPropertyVetoException;
import wt.util.WTStandardDateFormat;

import com.ptc.core.relcontext.server.RelContextHelper;
import com.ptc.netmarkets.model.NmObject;
import com.ptc.netmarkets.model.NmOid;
import com.ptc.netmarkets.util.beans.NmCommandBean;
import com.ptc.netmarkets.util.table.NmHTMLTable;
import com.ptc.netmarkets.util.table.NmHTMLTableModel;
import com.ptc.projectmanagement.deliverable.PlanDeliverable;
import com.ptc.projectmanagement.plan.Plan;
import com.ptc.projectmanagement.plan.PlanActivity;
import com.ptc.projectmanagement.plan.PlanHelper;
import com.ptc.projectmanagement.plan.Plannable;
import com.ptc.projectmanagement.plannable.PlannableHelper;
import com.ptc.windchill.history.HistoryRecord;
import com.ptc.windchill.history.HistoryRecordLink;
import com.ptc.windchill.history.HistoryXMLHelper;
import com.ptc.windchill.history.XMLGeneratorHelper;

import ext.com.org.OrgUtil;

public class TianmaProjectUtil {
	// public static String[] bosenPhaseNames = null;
	public static boolean VERBOSE = false;// 是否打印调试信息
	public static final String CLASSNAME=TianmaProjectUtil.class.getName();
	public static TianmaProjectHelper guideProjectHelper = new TianmaProjectHelper();
	public static StandardCalendarService scService = new StandardCalendarService();

	static {
		try {
			// 获取调试信息开关
			VERBOSE = (WTProperties.getLocalProperties()).getProperty("ext.generic.project.reports.verbose", false);

		} catch (Throwable throwable) {
			throw new ExceptionInInitializerError(throwable);
		}
	}

	private HashMap getAllDepGroup() {
		HashMap group = new HashMap();
		try {
			Enumeration allGroup = OrganizationServicesHelper.manager.allGroups();
			Object thisObj = null;
			while (allGroup.hasMoreElements()) {
				thisObj = (WTGroup) allGroup.nextElement();
				String groupName = ((WTGroup) thisObj).getName();
				String groupDes = ((WTGroup) thisObj).getDescription();
				if (groupDes.contains("部门")) {
					group.put(groupName, thisObj);
				}
			}
			return group;
		} catch (WTException wte) {
			wte.printStackTrace();
			return null;
		}
	}

	/*
	 * 根据用户获取用户所属的组,返回的组名带一个"_",产值相关代码专用比如:电控部_部长,网络信息部_统计员
	 */
	public static String getWTGroupNameByWTUser(WTUser user) throws WTException {
		ArrayList immediateParentGroups = new ArrayList();
		try {
			immediateParentGroups = OrgUtil.immediateParentGroups(user);
		} catch (Exception e) {
			throw new WTException(e);
		}
		for (int i = 0; i < immediateParentGroups.size(); i++) {
			WTGroup group = (WTGroup) immediateParentGroups.get(i);
			String groupName = group.getName();
			String groupDes = group.getDescription();
			if (groupDes.contains("部门"))
				return groupName;
		}
		return null;
	}

	/**
	 * 类的私有方法，输出调试信息
	 * 
	 * @param info
	 *            需要输出的调试信息
	 * @return null
	 * @exception null
	 **/

	private static void outDebugInfo(String info) {
		if (VERBOSE)
			System.out.println("TianmaProjectUtil>>" + info);
	}

	/**
	 * 获取时间的年月日的显示字符串
	 * 
	 * @param time
	 *            需要获取时间的时间戳
	 * @return 时间相关的显示字符串值,格式为年-月-日
	 * @exception null
	 * 
	 * <br>
	 * <br>
	 *                <b>Revision History</b> <br>
	 *                <b>Rev:</b> 1.0 2007-9-19, Lauren <br>
	 *                <b>Comment:</b> Initial release.
	 **/
	private static String getTimeStampDateStr(Timestamp time) {
		if (time == null)
			return "";
		TimeZone tz = WTContext.getContext().getTimeZone();
		SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
		formatter.setTimeZone(tz);
		String dateString = formatter.format(time);
		return dateString;
	}

	/**
	 * 获取时间的年月的显示字符串
	 * 
	 * @param time
	 *            需要获取时间的时间戳
	 * @return 时间相关的显示字符串值,格式为年-月
	 * @exception null
	 * 
	 * <br>
	 * <br>
	 *                <b>Revision History</b> <br>
	 *                <b>Rev:</b> 1.0 2007-9-19, Lauren <br>
	 *                <b>Comment:</b> Initial release.
	 **/
	private static String getTimeStampDateStr2(Timestamp time) {
		if (time == null)
			return "";
		int year = time.getYear() + 1900;
		int month = time.getMonth() + 1;
		return year + "-" + month;
	}

	/**
	 * 根据项目获取对应的项目任务
	 */
	public static QueryResult getPlanActivityByProject(Project2 project) throws WTException {
		QuerySpec qs = null;
		QueryResult qr = null;
		qs = new QuerySpec(PlanActivity.class);
		ReferenceFactory rf = new ReferenceFactory();
		ObjectIdentifier objId = ObjectIdentifier.newObjectIdentifier(rf.getReferenceString(project));
		SearchCondition sc = new SearchCondition(PlanActivity.class, "containerReference.key", SearchCondition.EQUAL, objId);
		qs.appendSearchCondition(sc);
		qr = PersistenceHelper.manager.find(qs);
		return qr;
	}

	/**
	 * 搜索项目
	 * 
	 * @param name
	 * @return
	 * @throws WTException
	 */
	public static QueryResult queryProject() throws WTException {
		Vector<Project2> rtn = new Vector<Project2>();

		QuerySpec querySpec = new QuerySpec(Project2.class);
		// SearchCondition sc = new SearchCondition(Project2.class,
		// "pseudoType", "=", 1);
		SearchCondition sc = new SearchCondition(Project2.class, "pseudoType", "=", 1);
		querySpec.appendWhere(sc);
		QueryResult allProject2 = PersistenceHelper.manager.find(querySpec);
		System.out.println("总数:" + allProject2.size());
		return allProject2;
	}

	/**
	 * 根据当前用户获取所有项目
	 * 
	 * @param commandBean
	 * @return
	 * @throws WTPropertyVetoException
	 * @throws WTException
	 */
	public static QueryResult getProjectsByPrincipal(NmCommandBean commandBean) throws WTPropertyVetoException, WTException {
		QueryResult queryresult1 = RelContextHelper.getProjectsInNetwork(SessionHelper.getPrincipal(), commandBean);
		return queryresult1;
	}

	/**
	 * 根据项目获取对应的项目交付物
	 */
	public static QueryResult getPlanDeliverableByProject(Project2 project) throws WTException {
		QuerySpec qs = null;
		QueryResult qr = null;
		qs = new QuerySpec(PlanDeliverable.class);
		ReferenceFactory rf = new ReferenceFactory();
		ObjectIdentifier objId = ObjectIdentifier.newObjectIdentifier(rf.getReferenceString(project));
		SearchCondition sc = new SearchCondition(PlanDeliverable.class, "containerReference.key", SearchCondition.EQUAL, objId);
		qs.appendSearchCondition(sc);
		qr = PersistenceHelper.manager.find(qs);
		return qr;
	}

	/**
	 * 根据项目获取对应的项目交付物
	 */
	public static QueryResult getMilestoneByProject(Project2 project) throws WTException {
		QuerySpec qs = null;
		QueryResult qr = null;
		qs = new QuerySpec(PlanActivity.class);
		ReferenceFactory rf = new ReferenceFactory();
		ObjectIdentifier objId = ObjectIdentifier.newObjectIdentifier(rf.getReferenceString(project));
		SearchCondition sc = new SearchCondition(PlanActivity.class, "containerReference.key", SearchCondition.EQUAL, objId);
		qs.appendSearchCondition(sc);
		qr = PersistenceHelper.manager.find(qs);
		return qr;
	}

	/**
	 * 根据所输入的条件选择名称或者全名符合条件的用户
	 * 
	 * @param findString
	 *            查找的字符串
	 * @return Vector 用户列表
	 * @exception WTException
	 *                windchill基本的例外
	 **/
	public static Vector getUserList(String findString) throws WTException {
		outDebugInfo("findString>>>" + findString);
		if (findString == null)
			return null;
		if (findString.trim().length() == 0) {
			findString = "*";
		} else if (findString.contains("**")) {
			findString = findString.replace("**", "");
			if ("".equals(findString)) {
				findString = "*";
			}
		}
		Vector userList = new Vector();
		Enumeration userList1 = OrganizationServicesHelper.manager.findLikeUser("name", findString);
		outDebugInfo("userList1>>>" + userList1);

		while (userList1 != null && userList1.hasMoreElements()) {
			userList.add((WTUser) userList1.nextElement());
		}
		Enumeration userList2 = OrganizationServicesHelper.manager.findLikeUser("fullName", findString);

		outDebugInfo("userList2>>>" + userList2);
		while (userList2 != null && userList2.hasMoreElements()) {
			WTUser user = (WTUser) userList2.nextElement();
			if (!userList.contains(user))
				userList.add(user);
		}
		return userList;
	}

	/**
	 * 根据用户获取其能相关的本月内的任务列表并统计
	 * 
	 * @param userListStr
	 *            需要统计的人员的字符串,以逗号分割
	 * @return Vector 各相关人员的任务列表,内容是PeoplesListElement
	 * @exception WTException
	 *                windchill基本的例外
	 **/
	public static Vector getDeliverByPjForCurrUser(String pjOid) throws WTException {
		outDebugInfo(">>>>>>>>>>>>>getDeliverByPjForCurrUser()>>>>>>");
		if (pjOid == null)
			return null;
		Vector theDelivers = new Vector();
		ReferenceFactory rf = new ReferenceFactory();
		Project2 pj = (Project2) rf.getReference(pjOid).getObject();

		ProjectPlan pjPlan = pj.getProjectPlan();

		WTUser wtuser = (WTUser) wt.session.SessionHelper.getPrincipal();
		String userName = wtuser.getName();
		boolean flag = SessionServerHelper.manager.setAccessEnforced(false);
		try {
			QueryResult allDeliver = ProjResourceHelper.service.getDeliverables(pjPlan);
			while (allDeliver != null && allDeliver.hasMoreElements()) {
				Deliverable deliver = (Deliverable) allDeliver.nextElement();
				// modify by gaoxu
				// System.out.println("****deliver == "+deliver.getName());
				if (deliver.getTarget() == null) {
					int percent = deliver.getPercentComplete();
					// System.out.println("****Deliver percent =="+percent+"%");
					String ownerName = deliver.getOwnership().getOwner().getName();
					// Timestamp startTime = deliver.getStartTime();
					// outDebugInfo("startTime="+startTime);
					// if(ownerName.equalsIgnoreCase(userName) && (percent<100
					// && percent>=0) && startTime!=null && deliver.isEnabled())
					if (ownerName.equalsIgnoreCase(userName) && (percent < 100 && percent >= 0) && deliver.isEnabled()) {
						theDelivers.add(deliver);
					}
				}
				// end of
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		} finally {
			SessionServerHelper.manager.setAccessEnforced(flag);
		}
		outDebugInfo("<<<<<<<<<<<getDeliverByPjForCurrUser()<<<<<<<<<<<");
		return theDelivers;
	}

	public static String generateDoDeliverURL(String objectOid) throws WTException {
		String strURL = "";
		Properties properties = new Properties();
		try {
			properties.put("action", "DoDirectDeliverObject");
			properties.put("oid", objectOid);
			strURL = wt.httpgw.GatewayURL.buildAuthenticatedURL("wt.enterprise.URLProcessor", "processForm", properties).toString();
		} catch (WTException wtexception) {
			strURL = "";
		}
		return strURL;
	}

	/**
	 * 获取properties中的值
	 */
	private static String getPropertiesValue(String key) throws WTException {
		String valueInProperties = "";
		System.out.println(">>>> go getpropertiesValue >>>>");
		PropertyResourceBundle prBundle = (PropertyResourceBundle) PropertyResourceBundle.getBundle("ext.xinri.project.project"); // not
																																	// right
		System.out.println(">>>> go getbundle >>>>");
		try {
			byte[] temp = null;
			temp = key.getBytes("GB2312");
			key = new String(temp, "ISO-8859-1");
			temp = prBundle.getString(key).getBytes("ISO-8859-1");
			valueInProperties = new String(temp, "GB2312");

		} catch (Exception e) {
			e.printStackTrace();
		}

		return valueInProperties;
	}

	/*
	 * 得到类别
	 */
	public static String[] getTypes(String key, String[] result) throws WTException, UnsupportedEncodingException {
		System.out.println(">>>> go getTypeVector >>>>");
		String typesStr = getPropertiesValue(key);
		System.out.println("typesStr=" + typesStr);
		if (typesStr != null && typesStr.length() > 0) {
			result = typesStr.split(",");
			for (int i = 0; i < result.length; i++)
				System.out.println(result[i].trim());
		}
		return result;

	}

	public static Persistable getTargetOfDeliverable(Deliverable deliverable) throws WTException {
		boolean flag = SessionServerHelper.manager.setAccessEnforced(false);
		Persistable subject = deliverable.getTarget();
		SessionServerHelper.manager.setAccessEnforced(flag);
		return subject;
	}

	/**
	 * 通过组名获取组，将组成员获取
	 * 
	 * @param groupName
	 * @return
	 * @throws WTException
	 */
	public static Vector addGroupUser1(String groupName) throws WTException {
		Vector participants = new Vector();
		WTGroup wtgroup = getGroupByName(groupName);
		if (wtgroup != null) {
			Enumeration members = wtgroup.members();
			while (members != null && members.hasMoreElements()) {
				wt.org.WTPrincipal wtp = ((wt.org.WTPrincipal) members.nextElement());
				addUser(participants, wtp);
			}
		}
		return participants;
	}

	/**
	 * 循环添加用户，如果是组 继续循环
	 * 
	 * @param participants
	 * @param wtp
	 * @throws WTException
	 */
	public static void addUser(Vector participants, WTPrincipal wtp) throws WTException {
		if (wtp instanceof WTUser && !(participants.contains(wtp)))
			participants.add(wtp);
		if (wtp instanceof WTGroup) {
			Enumeration members = ((WTGroup) wtp).members();
			while (members != null && members.hasMoreElements()) {
				wt.org.WTPrincipal wtp1 = ((wt.org.WTPrincipal) members.nextElement());
				addUser(participants, wtp1);
			}
		}
	}

	/**
	 * 通过组名称查询 ,支持模糊查询。
	 * 
	 * @param groupName
	 *            组名称
	 * @return
	 * @throws WTException
	 */
	public static WTGroup getGroupByName(String groupName) throws WTException {
		// Vector wtgroup=new Vector();
		if (groupName == null)
			return null;
		if (groupName.trim().length() == 0)
			groupName = "*";
		WTGroup wtgroup = null;
		QuerySpec qs = null;
		QueryResult qr = null;

		qs = new QuerySpec(WTGroup.class);
		SearchCondition sc = new SearchCondition(WTGroup.class, WTGroup.NAME, SearchCondition.LIKE, groupName);
		qs.appendSearchCondition(sc);
		qr = PersistenceHelper.manager.find(qs);
		while (qr.hasMoreElements()) {
			wtgroup = (WTGroup) qr.nextElement();
			break;
		}

		return wtgroup;
	}

	/**
	 * 通过组名称查询,支持模糊查询
	 * 
	 * @param groupName
	 * @return
	 * @throws WTException
	 */
	public static Vector getGroupsByName(String groupName) throws WTException {
		System.out.println("groupName>>>" + groupName);
		Vector vec = new Vector();
		if (groupName == null)
			return vec;
		if (groupName.trim().length() == 0) {
			groupName = "*";
		} else {
			groupName = groupName.replace("*", "%");
		}

		System.out.println("groupName>>>" + groupName);
		QuerySpec qs = null;
		QueryResult qr = null;

		qs = new QuerySpec(WTGroup.class);
		SearchCondition sc = new SearchCondition(WTGroup.class, WTGroup.NAME, SearchCondition.LIKE, "%" + groupName + "%");
		qs.appendSearchCondition(sc);
		qr = PersistenceHelper.manager.find(qs);
		System.out.println("qr.size()>>>" + qr.size());
		while (qr.hasMoreElements()) {
			WTGroup group = (WTGroup) qr.nextElement();
			if (!vec.contains(group)) {
				vec.add(group);

			}

		}

		return vec;
	}

	/**
	 * 获取系统中定义项目状态
	 * 
	 * @param table
	 * @throws WTException
	 */
	public static ArrayList getProjStateList(NmHTMLTable table) throws WTException {
		outDebugInfo("getProjStateList(" + table + ")");

		ArrayList stateList = new ArrayList();

		NmHTMLTableModel tm = table.getTableModel();
		Object table_am = table.getActionModel();
		int rowCount = tm.getRowCount();
		outDebugInfo("rowCount>>>>" + rowCount);
		for (int tablei = 0; tablei < rowCount; tablei++) {
			String state = "";
			NmObject nmo = tm.getObject(tablei);
			outDebugInfo("nmo>>>>" + nmo);

			NmOid targetOid = nmo.getOid();

			Project2 project2 = getProject2(targetOid);

			outDebugInfo("project2>>>>" + project2);

			if (project2 == null) {
				continue;
			}

			String TempState = project2.getContainerTeamManagedInfo().getState().toString();
			if (TempState != null) {
				state = TempState;
			}

			if (!stateList.contains(state)) {
				stateList.add(state);
			}
		}

		return stateList;

	}

	/**
	 * 通过oid 获取项目
	 * 
	 * @param nmoid
	 * @return
	 * @throws WTException
	 */
	private static Project2 getProject2(NmOid nmoid) throws WTException {
		if (nmoid == null) {
			return null;
		}
		ObjectIdentifier objectidentifier = nmoid.getOid();
		Persistable persistable = PersistenceHelper.manager.refresh(objectidentifier);
		if (persistable instanceof ProjectPlan) {
			return ((ProjectPlan) persistable).getProject();
		}
		if (persistable instanceof Project2) {
			return (Project2) persistable;
		} else {
			return null;
		}
	}

	/**
	 * 根据项目名称、预估开时间、预估结束时间 查询符合条件的项目
	 * @param projectName 项目名称
	 * @param startDate 开始时间范围
	 * @param endDate   结束时间范围
	 * @return
	 */
	public static QueryResult queryProjectForMileStoneReport(String projectName, Date startDate, Date endDate)  {
		QueryResult qr = null;
		try {
			
			QuerySpec qs = new QuerySpec(Project2.class);
			if (projectName.trim().length() == 0) {
				projectName = "*";
			} else {
				projectName = projectName.replace("*", "%");
			}
			SearchCondition sc1 = new SearchCondition(Project2.class, Project2.NAME, SearchCondition.LIKE, "%"+projectName+"%");
			qs.appendSearchCondition(sc1);
			
			if(startDate!=null&&endDate!=null ){
				qs.appendAnd();
				Timestamp beginDate = new Timestamp(startDate.getTime());
				Timestamp finshDate = new Timestamp(endDate.getTime());
				AttributeRange range = new AttributeRange(beginDate, finshDate);
				SearchCondition sc3 = new SearchCondition(Project2.class, Project2.CREATE_TIMESTAMP, true, range);
				qs.appendSearchCondition(sc3);
				//qs.appendWhere(sc3);
				
				
			}
			qs.appendOrderBy(Project2.class, Project2.CREATE_TIMESTAMP, true);
			outDebugInfo(qs.toString());
			qr=PersistenceHelper.manager.find(qs);
			
		} catch (WTException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			 qr=new QueryResult();
		}finally{
			return qr;
		}
         
	}
	
	/**
	 *根据项目获取计划根节点
	 */
	public static Plan getPlan(Project2 project) throws WTException {
		ReferenceFactory rf = new ReferenceFactory();
		return (Plan) PlanHelper.service.getPlan((ObjectReference) rf
				.getReference(project));
	}
	
	
	
	/**
	 * 根据container 查询container 下的所以问题报告
	 * @param con 
	 * @return QueryResult 结果集
	 */
	public static QueryResult queryPRWithContiner(WTContainer con) {
		QueryResult qr=null;
		
		try {
			QuerySpec qs = new QuerySpec();
			int i=qs.appendClassList(WTChangeIssue.class, true);
			int j=qs.appendClassList(WTChangeIssueMaster.class, false);
			
			qs.appendOpenParen();
			SearchCondition sc1=new SearchCondition(WTChangeIssueMaster.class, "containerReference.key.id", SearchCondition.EQUAL,  PersistenceHelper.getObjectIdentifier(con).getId());
			qs.appendWhere(sc1,new int[] {j});
			qs.appendCloseParen();
			
			qs.appendAnd();
			qs.appendOpenParen();
			SearchCondition sc2=new SearchCondition(WTChangeIssue.class, "masterReference.key.id", WTChangeIssueMaster.class, "thePersistInfo.theObjectIdentifier.id");
			qs.appendWhere(sc2,new int[] {  i,j });
			qs.appendCloseParen();
			qs.appendOrderBy(WTChangeIssue.class, WTChangeIssue.CREATE_TIMESTAMP,true);
			outDebugInfo(qs.toString());
			qr=PersistenceHelper.manager.find(qs);
		} catch (WTException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			qr=new QueryResult();
		} finally{
			return qr;
		}
		
	}
	
	
	/**
	 * 获取里程碑的完成时间的修改记录:查询 HistoryRecordLink 、HistoryRecord
	 * 
	 * @param activity 活动
	 * @return QueryResult 结果集
	 */
	public static QueryResult queryHistoryRecordPlanActivity(Project2 proj) {
		System.out.println("queryHistoryRecordPlanActivity");
		QueryResult qr = null;
		System.out.println(PlanActivity.MILESTONE);
		try {
			QuerySpec qs = new QuerySpec();
			int i = qs.appendClassList(HistoryRecord.class, true);
			int j = qs.appendClassList(HistoryRecordLink.class, true);
			int k = qs.appendClassList(PlanActivity.class, true);

			qs.appendOpenParen();
			SearchCondition sc1 = new SearchCondition(HistoryRecordLink.class, "roleAObjectRef.key.id", PlanActivity.class, "thePersistInfo.theObjectIdentifier.id");
			qs.appendWhere(sc1, new int[] { j,k });
			qs.appendCloseParen();

			qs.appendAnd();
			qs.appendOpenParen();
			SearchCondition sc2 = new SearchCondition(HistoryRecord.class, HistoryRecord.LABEL, SearchCondition.EQUAL, "EPP_FINISH_CHANGE");
			qs.appendWhere(sc2, new int[] { i });
			qs.appendCloseParen();

			qs.appendAnd();
			qs.appendOpenParen();
			SearchCondition sc3 = new SearchCondition(HistoryRecordLink.class, "roleBObjectRef.key.id", HistoryRecord.class, "thePersistInfo.theObjectIdentifier.id");

			qs.appendWhere(sc3, new int[] { j, i });
			qs.appendCloseParen();

			qs.appendAnd();
			qs.appendOpenParen();
			SearchCondition sc4 = new SearchCondition(PlanActivity.class, "milestone", SearchCondition.IS_TRUE);
			qs.appendWhere(sc4, new int[] { k });
			qs.appendCloseParen();
			
			qs.appendAnd();
			qs.appendOpenParen();
			SearchCondition sc5 = new SearchCondition(PlanActivity.class, "containerReference.key.id", SearchCondition.EQUAL, PersistenceHelper.getObjectIdentifier(proj).getId());
			qs.appendWhere(sc5, new int[] { k });
			qs.appendCloseParen();
			

			OrderBy orderby = new OrderBy(new ClassAttribute(HistoryRecord.class, HistoryRecord.MODIFY_TIMESTAMP), false);	//true为降序，false为升序
			qs.appendOrderBy(orderby, new int[]{i});
			
			System.out.println("qs>>>>>>>>>>>>>"+qs);
			qr = PersistenceHelper.manager.find(qs);
		} catch (WTException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.out.println(e);
			qr = new QueryResult();
		} finally {
			System.out.println(qr);
			return qr;
		}

	}
	
	/**
	 * 从ECN中获取所有CA中的（受影响成品）
	 * @param changeOrder
	 * @return
	 * @throws WTException 
	 */
	public static Vector<WTPart> getProductOfECN(WTChangeOrder2 changeOrder) throws WTException {
		if(VERBOSE) {
			System.out.println(">>>>>>>>>>>>>>>>>" + CLASSNAME + ".getProductOfECN()");
			System.out.println(changeOrder.getName()+"|"+changeOrder.getNumber());
		}
		Vector<WTPart> product = new Vector<WTPart>();
		
		QueryResult ecas = ChangeHelper2.service.getChangeActivities(changeOrder);

		while (ecas != null && ecas.hasMoreElements()) {
			WTChangeActivity2 ca = (WTChangeActivity2) ecas.nextElement();
			if (VERBOSE) {
				System.out.println("ca.getIdentity() =" + ca.getIdentity());
			}
			QueryResult qr = ChangeHelper2.service.getChangeablesBefore(ca,true);
			while (qr != null&&qr.hasMoreElements()) {
				Changeable2 changeable = (Changeable2) qr.nextElement();
				if (changeable instanceof WTPart) {
					WTPart aWTPart = (WTPart)changeable;
					System.out.println(aWTPart.getName()+" aWTPart.isEndItem() = "+aWTPart.isEndItem());
					if (aWTPart.isEndItem() && isPersistableInobjVector(product, aWTPart)==false) {
						product.add(aWTPart);
					}
				}
			}
		}
		
		if(VERBOSE) {
			System.out.println("<<<<<<<<<<<<<<<<<" + CLASSNAME + ".getProductOfECN()");
		}
		return product;
	}
	
	/**
	 * 检查某一个可持续对象是否在列表中
	 * @param objVector 检查的列表
	 * @param destination 想要检查的对象
	 * @return 如果对象在列表中，返回true，否则，返回false  
	 * @throws WTException
	 */
	public static boolean isPersistableInobjVector(Vector objVector, Persistable destination) 
		throws WTException
	{
		if((objVector==null) || (objVector.size()<=0))
			return false;
		if(objVector.contains(destination))
		{
			return true;
		}
		boolean flag= false;
		for(int i=0; i<objVector.size(); i++)
		{
			flag= PersistenceHelper.isEquivalent((Persistable)objVector.elementAt(i), destination);
			if(flag)
				return flag;
		}
		return flag;
	}
	
	/**
	 * 获取列表中对象名称集合，以字符串形式返回
	 * @param vec
	 * @return
	 */
	public static String getVectorsName(Vector vec){
		StringBuffer buffer=new StringBuffer();
		for(int k=0;k<vec.size();k++){
			WTObject obj=(WTObject) vec.get(k);
			if(obj instanceof WTPart){
				WTPart part =(WTPart) obj;
				if("".equals(buffer.toString())){
					buffer.append(part.getName());
				}else{
					buffer.append(";").append(part.getName());
				}
			}else if( obj instanceof WTDocument){
				WTDocument doc =(WTDocument) obj;
				if("".equals(buffer.toString())){
					buffer.append(doc.getName());
				}else{
					buffer.append(";").append(doc.getName());
				}
			}else if(obj instanceof EPMDocument){
				EPMDocument epm =(EPMDocument) obj;
				if("".equals(buffer.toString())){
					buffer.append(epm.getName());
				}else{
					buffer.append(";").append(epm.getName());
				}
			}else if(obj instanceof ChangeActivity2){
				ChangeActivity2 eca =(ChangeActivity2) obj;
				if("".equals(buffer.toString())){
					buffer.append(eca.getName());
				}else{
					buffer.append(";").append(eca.getName());
				}
			}
		}
		
		return buffer.toString();
	}
	
	/*
	 * 得到ECN所有的所有受影响的数据
	 */	  
	public static Vector getChangeablesBefore(WTChangeOrder2 ecn, Vector beforeVector)
        throws WTException, WTPropertyVetoException, IOException
    {
        for(Enumeration enumca = ChangeHelper2.service.getChangeActivities(ecn); enumca.hasMoreElements();)
        {
            WTChangeActivity2 ca = (WTChangeActivity2)enumca.nextElement();
            QueryResult qr = ChangeHelper2.service.getChangeablesBefore(ca);
            {
            	if(qr.hasMoreElements())
            	{
            		while(qr.hasMoreElements())
            		{
            			Changeable2 changeable = (Changeable2)qr.nextElement();
            			if(!beforeVector.contains(changeable))
                    	{
                        	beforeVector.add(changeable);
                    	}
            		}
            	}
            }
        }
        return beforeVector;
     }
	
	
	/*
	 * 得到ECN所有的所有产生的数据
	 */	  
	public static Vector getChangeablesAfter(WTChangeOrder2 ecn, Vector afterVector)
        throws WTException, WTPropertyVetoException, IOException
    {
        for(Enumeration enumca = ChangeHelper2.service.getChangeActivities(ecn); enumca.hasMoreElements();)
        {
            WTChangeActivity2 ca = (WTChangeActivity2)enumca.nextElement();
            QueryResult qr = ChangeHelper2.service.getChangeablesAfter(ca);
            {
            	if(qr.hasMoreElements())
            	{
            		while(qr.hasMoreElements())
            		{
            			Changeable2 changeable = (Changeable2)qr.nextElement();
            			if(!afterVector.contains(changeable))
                    	{
            				afterVector.add(changeable);
                    	}
            		}
            	}
            }
        }
        return afterVector;
     }
	
	
	/**
	 * 里程碑变更记录jsp脚本输出
	 * @param proj
	 * @return
	 * @throws WTException 
	 */
	public static String getMileStoneChangeListOutPrint(Project2 proj) throws WTException{
		StringBuffer printBuffer = new StringBuffer();
		int i = 0;
		Plan plan = TianmaProjectUtil.getPlan(proj);
		WTCollection wtc = PlannableHelper.service.getAllChildren((Plannable) plan);
		Iterator itor = wtc.persistableIterator();
		// HashMap map = new HashMap();
		int cellY = 0;// 列
		TreeMap postionTable=new TreeMap();//记录里程碑输出表的位置
		Hashtable mileStoneTable=new Hashtable();//记录项目有多少里程碑活动
		Hashtable firsttimeTable=new Hashtable();//记录第一次预估计完成时间
		Hashtable increatetimeTable=new Hashtable();//每获取到一次当前值就更新一次,记录时间会随着获取不断改变
		Hashtable postionRemaincTable=new Hashtable();//记录是否里程碑报表没有输出
		Vector vecOrder=new Vector();//里程碑名称输出的顺序
		TreeMap outTable=new TreeMap();//修改次数的
		printBuffer.append("<table border=\"1\" >");
		printBuffer.append("<tr>");
		printBuffer.append("<td>");
		printBuffer.append("</td>");
		//先将项目中所有的里程碑名称输出
		if (itor.hasNext()) {
			while (itor.hasNext()) {
				PlanActivity planActi = (PlanActivity) itor.next();
				if (planActi != null) {
					// 非里程碑 不做处理
					if (!planActi.isMilestone()) {
						continue;
					}
					// 计划根节点不做处理
					if (planActi.getLineNumber() == 0) {
						continue;
					}
					
					String activityName=planActi.getName().trim();
					long planActiID=PersistenceHelper.getObjectIdentifier(planActi).getId();
					String actiID=activityName+"|"+planActiID;//活动标示
					printBuffer.append("<td size=\"3\">");
					printBuffer.append(activityName);
					outDebugInfo("第"+i+" 行的>>>第"+(cellY+1)+" 列 "+activityName);
					postionTable.put(actiID, (cellY+1));
					mileStoneTable.put(actiID,planActi);
					postionRemaincTable.put(actiID, planActi);//获取里程碑记录,然后获取一条就删除已此表格一条，如果到最后还有记录则说明该条是没有变更的
					vecOrder.add(actiID);
					cellY++;
					printBuffer.append("</td>");
					
				}
		     }
		}
		printBuffer.append("</tr>");
		i++;
		//获取有更改记录的对象
		QueryResult qr=TianmaProjectUtil.queryHistoryRecordPlanActivity(proj);
		System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>"+qr.size());
		int w=1;//记录修改次数
		if(qr!=null){
			
			while(qr.hasMoreElements()){
				Persistable pb[]=(Persistable[]) qr.nextElement();
				HistoryRecord hr=(HistoryRecord) pb[0];
				HistoryRecordLink hrl=(HistoryRecordLink) pb[1];
				PlanActivity  activity=(PlanActivity) pb[2];
				if(activity==null ||"0".equals(activity.getLineNumber())){
					continue;
				}
				
				String activityName=activity.getName()==null?"":activity.getName().trim();
				outDebugInfo("find planactivity>>>>"+activityName);
				long planActiID=PersistenceHelper.getObjectIdentifier(activity).getId();
				String actiID=activityName+"|"+planActiID;//活动标示
				
				//String esCompTimeStr= (String) vec.get(0);//初始估计完成时间
				String s2 = hr.getPersistInfo().getObjectIdentifier().getStringValue();
				System.out.println(">>>>>>"+s2);
				
                String s3 = XMLGeneratorHelper.getHistoryXML((new StringBuilder()).append("OR:").append(s2).toString());
                
                Document document = HistoryXMLHelper.parse(s3);
                String s4 = hr.getLabel();
                System.out.println(">>>>>>"+s4);
                NodeList nodelist = document.getElementsByTagName(s4);
                
                String changeTimeStr="";//获取记录时间
                if(nodelist.getLength() > 0)
                {
                    Node node = nodelist.item(0);
                    System.out.println(">>>>>>"+node.getTextContent());
                    String contentFinishTime=node.getTextContent();
                    Date finshDate=null;
                    SimpleDateFormat f = new SimpleDateFormat("yyyy/MM/dd"); // 格式化为
                    try{
                    	f.parse(contentFinishTime);
                    }
                    catch (ParseException e) {
            			SimpleDateFormat f2 = new SimpleDateFormat("yyyy-MM-dd"); // 格式化为
            			// hhmmss
            			try {
            				finshDate = f2.parse(contentFinishTime);
            			} catch (ParseException e1) {
            				// TODO Auto-generated catch block
            				e1.printStackTrace();
            			}

            		}
                    
                    changeTimeStr= WTStandardDateFormat.format(finshDate,"yyyy/MM/dd") ;
                   
                    outDebugInfo("changeTimeStr>>>"+changeTimeStr);
                }
                //判断当前活动节点是否有记录过了
                if(firsttimeTable.get(actiID)==null){
                	outDebugInfo("activityName:"+actiID+" 记录没有计算过,第一次添加");
                	firsttimeTable.put(actiID, changeTimeStr);
                	increatetimeTable.put(actiID, changeTimeStr);
                	if(postionRemaincTable.containsKey(actiID)){
                		postionRemaincTable.remove(actiID);//在剩余表中删除该条记录
                	}
                	
                }else{
                
                	Hashtable vecOut=new Hashtable();
                	increatetimeTable.remove(actiID);
                	increatetimeTable.put(actiID, changeTimeStr);
                	Hashtable out1Table=new Hashtable();//输出条目
                	//本次修改与非本次修改 在时间上加_target 与_other 区别
                	out1Table.put(actiID, changeTimeStr+"_target");//本次修改条目  
                	//获取不是本次修改的条目的记录
                	Iterator mileItor=mileStoneTable.keySet().iterator();
                	while(mileItor.hasNext()){
                		String mileKey=mileItor.next().toString();
                		if(!mileKey.equals(actiID)){
                			String finshTime=increatetimeTable.get(mileKey)==null?"":increatetimeTable.get(mileKey).toString();
                    		//out1Table.put(mileKey, finshTime);
                    		out1Table.put(mileKey, finshTime+"_other");//非本次修改
                		}
                		
                	}
                	
                	outTable.put(w, out1Table);
                	
                	outDebugInfo("activityName:"+activityName+" 记录意见计算过,需要更新记录值");
                	w++;
                }
				
			}
		}
		outDebugInfo("*************************获取记录完成***************");
		printBuffer.append("<tr>");
		printBuffer.append("<td>");
		printBuffer.append("初始估计完成时间");
		printBuffer.append("</td>");
		
		outDebugInfo("第"+i+"行第0列:初始估计完成时间");
		
		//剩余的还未处理
		//初始估计完成时间输出
		
		for(int ww=0;ww<vecOrder.size();ww++){
			String actiID=vecOrder.get(ww).toString();
			outDebugInfo(actiID);
			//mileStoneTable.get(actiID);
			String finshTimeTemp=firsttimeTable.get(actiID)==null?"":firsttimeTable.get(actiID).toString();
			outDebugInfo(finshTimeTemp);
			outDebugInfo(""+"".equals(finshTimeTemp));
			outDebugInfo(""+postionRemaincTable.containsKey(actiID));
			//如果第一个时间为空且是剩余记录，说明该记录没有被修改
			if("".equals(finshTimeTemp)&&postionRemaincTable.containsKey(actiID)){
				PlanActivity actTemp=(PlanActivity) postionRemaincTable.get(actiID);
				finshTimeTemp= WTStandardDateFormat.format(actTemp.getFinishDate(),"yyyy/MM/dd") ;
			}
			
			printBuffer.append("<td>");
			printBuffer.append(finshTimeTemp);
			printBuffer.append("</td>");
		}
		
    	printBuffer.append("</tr>");
		
		i++;//行增加
		outDebugInfo("out put the line:"+i);
		Iterator iterator=outTable.keySet().iterator();
		printBuffer.append("<tr>");
		while(iterator.hasNext()){
			printBuffer.append("<tr>");
			Object key= iterator.next();
			Hashtable table=(Hashtable) outTable.get(key);
			outDebugInfo("key>>>>>>"+key);
			printBuffer.append("<td>");
			printBuffer.append("第"+key+"次更改");
			printBuffer.append("</td>");
			//outDebugInfo(strKey);
			for(int kk=0;kk<vecOrder.size();kk++){
				String actiID=vecOrder.get(kk).toString();
				String timeTemp=table.get(actiID).toString();
				String strTemp[]=timeTemp.split("_");
				String finshTimeTemp=strTemp[0];
				if(timeTemp.contains("_target")){
					if("".equals(finshTimeTemp)&&postionRemaincTable.containsKey(actiID)){
						PlanActivity actTemp=(PlanActivity) postionRemaincTable.get(actiID);
						finshTimeTemp= WTStandardDateFormat.format(actTemp.getFinishDate(),"yyyy/MM/dd") ;
					}
					
					printBuffer.append("<td>");
					printBuffer.append("<font style=\"background:yellow\">");
					printBuffer.append(finshTimeTemp);
					printBuffer.append("</font>");
					printBuffer.append("</td>");
					
				}else {
					
					if("".equals(finshTimeTemp)&&postionRemaincTable.containsKey(actiID)){
						PlanActivity actTemp=(PlanActivity) postionRemaincTable.get(actiID);
						finshTimeTemp= WTStandardDateFormat.format(actTemp.getFinishDate(),"yyyy/MM/dd") ;
					}
					printBuffer.append("<td>");
					//printBuffer.append("<font color=LIGHT_GREEN>");
					printBuffer.append(finshTimeTemp);
					//printBuffer.append("</font>");
					printBuffer.append("</td>");
				}
			}
			
			
			 printBuffer.append("</tr>");
			 i++;

		}
		printBuffer.append("</table>");
		
		return printBuffer.toString();
	}
	
}
